package com.onerway.util;

import com.onerway.common.TreeMapable;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.TreeMap;

@Slf4j
public class SignUtil {

    public static String sign(TreeMapable params, String secret) {
        return sign(params.toTreeMap(), secret);
    }

    /**
     * 生成签名
     *
     * @param params
     * @param secret 商户秘钥
     */
    public static String sign(TreeMap<String, Object> params, String secret) {
        // 将请求参数和商户密钥拼接成字符串
        String data = concatValue(params) + secret;
        // 生成签名
        String sign = hash(data);

        log.info("生成的签名 = {}", sign);

        return sign;
    }


    /**
     * 验证签名
     *
     * @param params
     * @param secret
     * @param sign
     * @return
     */
    public static boolean verifySign(TreeMap<String, Object> params, String secret, String sign) {
        String signed = sign(params, secret);
        return signed.equals(sign);
    }

    /**
     * 剔除空值和sign参数，拼接value成字符串
     *
     * @param data 请求参数
     * @return 拼接的字符串
     */
    private static String concatValue(TreeMap<String, Object> data) {
        StringBuilder sb = new StringBuilder();
        for (String key : data.keySet()) {
            if (data.get(key) != null && !data.get(key).equals("") && !key.equals("sign")) {
                sb.append(data.get(key));
            }
        }
        return sb.toString();
    }

    /**
     * 将拼接的字符串进行SHA-256加密
     *
     * @param concatStr 拼接的字符串
     * @return 加密后的字符串
     */
    private static String hash(String concatStr) {
        String sign = null;
        final String algorithm = "SHA-256";

        try {
            MessageDigest md = MessageDigest.getInstance(algorithm);

            // 隐藏秘钥
            log.info("拼接的字符串 = {}", concatStr.substring(0, concatStr.length() - 10) + "**");

            md.update(concatStr.getBytes(StandardCharsets.UTF_8));

            sign = byte2Hex(md.digest());

        } catch (NoSuchAlgorithmException e) {
            log.error("Error: NoSuchAlgorithmException, Algorithm {} is not available", algorithm, e);
        } catch (Exception e) {
            log.error("Error while encrypting message: {}", e.getMessage());
        }
        return sign;
    }

    /**
     * 将字节数组转换为十六进制字符串表示形式。
     *
     * @param bytes 需要转换的字节数组
     * @return 字节数组的十六进制字符串表示形式
     */
    private static String byte2Hex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte value : bytes) {
            String hexValue = Integer.toHexString(value & 0xFF);
            if (hexValue.length() == 1) {
                sb.append("0");
            }
            sb.append(hexValue);
        }
        return sb.toString();
    }
}